package com.sdleyou.treepro.common.service.impl;

import com.alibaba.fastjson.JSON;
import com.sdleyou.treepro.common.config.ApiConfig;
import com.sdleyou.treepro.common.constant.Constants;
import com.sdleyou.treepro.common.context.UserContext;
import com.sdleyou.treepro.common.exception.ServiceException;
import com.sdleyou.treepro.common.model.dao.*;
import com.sdleyou.treepro.common.model.dto.MissionRewardDTO;
import com.sdleyou.treepro.common.model.enums.ErrorCodeEnum;
import com.sdleyou.treepro.common.model.enums.UserStatusEnum;
import com.sdleyou.treepro.common.model.utils.RandomUtil;
import com.sdleyou.treepro.common.model.vo.UserVO;
import com.sdleyou.treepro.common.service.*;
import com.sdleyou.treepro.common.utils.*;
import com.sdleyou.treepro.manager.api.wechat.ServerController;
import com.sdleyou.treepro.system.cache.Cache;
import com.sdleyou.treepro.system.payment.UserConstantInterface;
import com.sdleyou.treepro.system.qiniu.UrlSafeBase64;
import com.sdleyou.treepro.system.security.model.User;
import net.sf.json.JSONObject;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class UserManagerImpl implements UserManager {

    private static Logger logger = LoggerFactory.getLogger(ServerController.class);

    @Autowired
    private ApiConfig apiConfig;
    @Autowired
    private Cache cache;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private PassportManager passportManager;
    @Autowired
    private UserPropManager userPropManager;
    @Autowired
    private UserPetManager userPetManager;
    @Autowired
    private MissionManager missionManager;
    @Autowired
    private UserMissionManager userMissionManager;
    @Autowired
    private LastRequestTimeManager lastRequestTimeManager;
    @Autowired
    private UserFriendManager userFriendManager;
    @Autowired
    private UserTreeManager userTreeManager;

    /**
     * 微信登陆
     *
     * @param code
     * @param ip
     * @param inviteUserId
     */
    @Override
    public Map<String, String> login(String code, String avatarUrl, String nickName, String gender, String city, String province, String ip, String inviteUserId) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", UserConstantInterface.WX_LOGIN_APPID);
        param.put("secret", UserConstantInterface.WX_LOGIN_SECRET);
        param.put("js_code", code);
        param.put("grant_type", UserConstantInterface.WX_LOGIN_GRANT_TYPE);
        // 发送请求
        String wxResult = HttpClientUtil.doGet(UserConstantInterface.WX_LOGIN_URL, param);
        //System.out.println("wxResult = " + wxResult);
        JSONObject jsonObject = JSONObject.fromObject(wxResult);
        // 获取参数返回的
        String session_key = jsonObject.get("session_key").toString();
        String open_id = jsonObject.get("openid").toString();
        String union_id;
        if (jsonObject.get("unionid") != null) {
            union_id = jsonObject.get("unionid").toString();
        } else {
            union_id = "";
        }
        // 根据返回的user实体类，判断用户是否是新用户，不是的话，更新最新登录时间，是的话，将用户信息存到数据库
        Query query = new Query(Criteria.where("user_id").is(open_id));
        UserDO insert_user = mongoTemplate.findOne(query, UserDO.class);
        if (insert_user != null) {
            Update update = new Update()
                    .set("last_login_time", DateUtil.toString(DateUtil.getDateline(), "yyyy-MM-dd HH:mm")).set("session_key", session_key);
            String lastLoginIp = insert_user.getLastLoginIp();
            if (!lastLoginIp.equals(ip)) {
                update.set("last_login_ip", ip);
            }
            if (!TextUtils.isEmpty(avatarUrl)) {
                update.set("face", avatarUrl);
            }
            if (!TextUtils.isEmpty(nickName)) {
                update.set("nickname", nickName);
            }
            if (!TextUtils.isEmpty(gender)) {
                update.set("gender", gender);
            }
            if (!TextUtils.isEmpty(city)) {
                update.set("city", city);
            }
            if (!TextUtils.isEmpty(province)) {
                update.set("province", province);
            }

            if (inviteUserId != null && !TextUtils.isEmpty(inviteUserId)) {
                //好友召回任务
                userMissionManager.updateMission(inviteUserId, "recall", null);
            }

            lastRequestTimeManager.setLoginList(insert_user.getUserId());
            if(!TextUtils.isEmpty(insert_user.getGmtCreate()) && !"null".equals(insert_user.getGmtCreate())) {
                update.set("duration", DateUtil.getDay(DateUtil.toString(Long.valueOf(insert_user.getGmtCreate()), "yyyy-MM-dd")));
            }

            mongoTemplate.updateFirst(query, update, UserDO.class);
        } else {
            //UserDO insert_user = new UserDO();
            insert_user = new UserDO();
            if(!TextUtils.isEmpty(avatarUrl) && !"null".equals(avatarUrl)){
                insert_user.setFace(avatarUrl);
            }else{
                insert_user.setFace(Constants.DEFAULT_HEAD);
            }
            if(!TextUtils.isEmpty(nickName) && !"null".equals(nickName)){
                insert_user.setNickname(nickName);
            }else{
                insert_user.setNickname("植树志愿者" + IdGen.getRandomName());
            }
            insert_user.setGender(gender);
            insert_user.setCity(city);
            insert_user.setProvince(province);
            insert_user.setLastLoginTime(DateUtil.toString(DateUtil.getDateline(), "yyyy-MM-dd HH:mm"));
            insert_user.setUserId(open_id);
            insert_user.setUnionId(union_id);
            insert_user.setRegisterIp(ip);
            insert_user.setLastLoginIp(ip);
            if (!TextUtils.isEmpty(inviteUserId)) {
                insert_user.setInviteUserId(inviteUserId);
            }

            // 设置默认值
            insert_user.setTotalTree(0);
            insert_user.setCurrentTree("");
            insert_user.setFertility(95);
            insert_user.setTotalValue(0);
            insert_user.setGmtCreate(DateUtil.getDateline() + "");
            insert_user.setGmtModified(DateUtil.getDateline() + "");
            insert_user.setTreeId("");
            insert_user.setGmtCreate(DateUtil.getDateline() + "");
            insert_user.setGmtModified(DateUtil.getDateline() + "");
            insert_user.setStatus(UserStatusEnum.PERSONAL.name());
            insert_user.setIsPlant(false);
            insert_user.setTreeStatus(2);
            insert_user.setCompanyId("");
            insert_user.setSessionKey(session_key);
            insert_user.setHasGTLH(false);
            insert_user.setHasQMYW(false);
            insert_user.setDuration(1);
            insert_user.setIsReceiveFirstLogin(false);
            insert_user.setWater(0);
            lastRequestTimeManager.setLoginList(insert_user.getUserId());

            // 添加到数据库
            mongoTemplate.insert(insert_user);

            //更新宠物状态 改为手动领取
            //userPetManager.userAddPet(insert_user.getUserId());
            //更新任务状态
            userMissionManager.updateMission(insert_user.getUserId());
            //更新道具状态
            userPropManager.updateUserProp(insert_user.getUserId());

            if (inviteUserId != null && !TextUtils.isEmpty(inviteUserId)) {
                //邀请任务
                userMissionManager.updateMission(inviteUserId, "invent", null);
                //添加好友
                userFriendManager.addFriend(inviteUserId, insert_user.getUserId(), "INVENT");
            }

            //设置登陆时间
            lastRequestTimeManager.update(insert_user.getUserId());
        }


        //获取上次的时间
        Long lastRequestTime = lastRequestTimeManager.getLastRequestTime(insert_user.getUserId());
        if (lastRequestTime != null) {
            long hourTime = DateUtil.getHourTime(lastRequestTime);
            if (hourTime >= 1) {
                //减少土地肥沃度
                subFertility(insert_user.getUserId(), Math.toIntExact(hourTime - 1 + 1));
            }
        }
        //减少树木成长值
        userTreeManager.setSubValue(insert_user.getUserId(), insert_user.getTreeId());

        String accessToken = passportManager.createToken(insert_user, apiConfig.getAccessTokenTimeout());
        cache.put(TokenKeyGenerate.generateBuyerAccessToken(insert_user.getUserId()), accessToken, apiConfig.getAccessTokenTimeout());

        // 封装返回小程序
        Map<String, String> result = new HashMap<>();
        //result.put("session_key", session_key);
        result.put("open_id", open_id);
        result.put("accessToken", accessToken);

        //设置生成水时间
        addWaterTime(insert_user.getUserId());
        //设置登陆时间
        lastRequestTimeManager.update(insert_user.getUserId());

        return result;
    }

    /**
     * 设置用户信息
     *
     * @param userId
     * @param userHead
     * @param userName
     * @param userGender
     * @param userCity
     * @param userProvince
     * @return
     */
    @Override
    public Map<String, String> setUserInfo(String userId, String userHead, String userName, String userGender, String userCity, String userProvince) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO insert_user = mongoTemplate.findOne(query, UserDO.class);
        if (insert_user != null) {
            Update update = new Update();

            if (!TextUtils.isEmpty(userHead)) {
                update.set("face", userHead);
            }
            if (!TextUtils.isEmpty(userName)) {
                update.set("nickname", userName);
            }
            if (!TextUtils.isEmpty(userGender)) {
                update.set("gender", userGender);
            }
            if (!TextUtils.isEmpty(userCity)) {
                update.set("city", userCity);
            }
            if (!TextUtils.isEmpty(userProvince)) {
                update.set("province", userProvince);
            }
            update.set("gmt_modified", DateUtil.getDateline());
            mongoTemplate.updateFirst(query, update, UserDO.class);
            //更新好友列表
            userFriendManager.update(userId, userName, userHead);
        }
        return null;
    }

    /**
     * 获取用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserVO userInfo(String userId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        UserVO userVO = new UserVO();
        if (userDO != null) {
            BeanUtils.copyProperties(userDO, userVO);
            userVO.setTreeWell(userDO.getTreeWell());
            //设置当前养殖的坑位兑换树苗所需要的能量
            Query queryWell = new Query(Criteria.where("user_id").is(userId).and("is_finish").is(false));
            WellDO wellDO = mongoTemplate.findOne(queryWell, WellDO.class);
            if (wellDO == null) {
                userVO.setPowerValue(0);
                userVO.setPreTreeId("");
            } else {
                Query queryTree = new Query(Criteria.where("tree_id").is(wellDO.getPreTreeId()));
                TreeDO treeDO = mongoTemplate.findOne(queryTree, TreeDO.class);
                if (treeDO == null) {
                    userVO.setPowerValue(0);
                } else {
                    userVO.setPowerValue(treeDO.getPowerValue());
                }
                userVO.setPreTreeId(wellDO.getPreTreeId());
                userVO.setPreTreeName(treeDO.getTreeName());
            }

            User user = UserContext.getUser();
            if (user != null) {
                String user_id = user.getUserId();
                if (userId.equals(user_id)) {
                    //自己
                    List<MissionRewardDTO> propList = new ArrayList<>();
                    MissionRewardDTO missionRewardDTO = new MissionRewardDTO();
                    missionRewardDTO.setPropType("WATER");
                    missionRewardDTO.setPropNumber(userVO.getWater() + "");
                    propList.add(missionRewardDTO);
                    userVO.setPropList(propList);

                    //设置生成水时间
                    addWaterTime(userId);

                    //判断是否是中午登陆 中午12点-14点
                    long startTime = DateUtil.startOfTodDay() + 43200;
                    long endTime = DateUtil.startOfTodDay() + 50400;
                    if (DateUtil.inRangeOf(startTime, endTime)) {
                        //中午12点-14点 完成任务
                        userMissionManager.updateMission(userId, "noon", null);
                    }

                    //设置登陆时间
                    lastRequestTimeManager.update(userId);
                } else {
                    //别人
                    if (userVO.getWater() != null) {
                        List<MissionRewardDTO> propList = new ArrayList<>();
                        MissionRewardDTO missionRewardDTO = new MissionRewardDTO();
                        missionRewardDTO.setPropType("WATER");
                        missionRewardDTO.setPropNumber("1");
                        propList.add(missionRewardDTO);
                        userVO.setPropList(propList);
                    }
                    //查询是否领取过
                    Query queryReceive = new Query(Criteria.where("receive_id").is(userId).and("date").is(DateUtil.startOfTodDay()));
                    ReceiveWaterDO one = mongoTemplate.findOne(queryReceive, ReceiveWaterDO.class);
                    if (one == null) {
                        userVO.setCanReceive(true);
                    } else {
                        userVO.setCanReceive(false);
                    }
                }
            }
        }
        return userVO;
    }

    /**
     * 选择种树类型后更新状态
     */
    @Override
    public Map<String, String> upDateAfterChooseTree(String userId, String treeId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO != null) {
            Update update = new Update();
            update.set("is_plant", true);
            update.set("tree_status", 0);
            update.set("tree_id", treeId);
            update.set("gmt_modified", DateUtil.getDateline() + "");
            mongoTemplate.updateFirst(query, update, UserDO.class);
        }
        return null;
    }

    /**
     * 养成树之后更新用户状态
     */
    @Override
    public Map<String, String> upDateAfterFinishPlant(String userId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        //update.set("total_tree", userDO.getTotalValue() + 1);//总养成树量
        Update update = new Update();
        update.set("tree_status", 1);
        update.set("gmt_modified", DateUtil.getDateline() + "");
        mongoTemplate.updateFirst(query, update, UserDO.class);
        return null;
    }

    /**
     * 已养成树兑换能量
     */
    @Override
    public Map<String, String> exchangeValue(String userId, String treeId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), "用户不存在");
        }
        Query queryTree = new Query(Criteria.where("tree_id").is(treeId));
        UserTreeDO userTreeDO = mongoTemplate.findOne(queryTree, UserTreeDO.class);
        if (userTreeDO == null) {
            throw new ServiceException(ErrorCodeEnum.E006.code(), "树木信息不存在");
        }
        BigDecimal total = new BigDecimal(userTreeDO.getGrowValue());
        BigDecimal current = new BigDecimal(userTreeDO.getCurrentValue());
        if (current.compareTo(total) < 0) {
            throw new ServiceException(ErrorCodeEnum.E302.code(), "成长值不足");
        }
        Update update = new Update();
        Integer growValue = userTreeDO.getRewardValue();
        update.set("total_value", userDO.getTotalValue() + growValue);//总能量增加
        update.set("tree_id", "");
        update.set("is_plant", false);
        update.set("tree_status", 2);
        update.set("gmt_modified", DateUtil.getDateline() + "");
        mongoTemplate.updateFirst(query, update, UserDO.class);
        Map<String, String> map = new HashMap<>();
        map.put("growValue", growValue + "");
        map.put("totalValue", userDO.getTotalValue() + growValue + "");
        return map;
    }

    @Override
    public void joinCompany(String userId, String companyId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO != null) {
            Update update = new Update();
            update.set("company_id", companyId);
            update.set("role", "STAFF");
            update.set("company_contribute", 0);
            mongoTemplate.updateFirst(query, update, UserDO.class);
        }
        return;
    }

    @Override
    public void chooseRole(String userId, String role) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        Update update = new Update();
        update.set("status", role);
        mongoTemplate.updateFirst(query, update, UserDO.class);
        return;
    }

    /**
     * 减少土地肥沃度
     *
     * @param times
     */
    @Override
    public void subFertility(String userId, Integer times) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO != null) {
            Integer fertility = userDO.getFertility();
            Integer sub = 5 * times;
            fertility -= sub;
            if (fertility < 30) {
                fertility = 30;
            }
            Update update = new Update();
            update.set("fertility", fertility);
            mongoTemplate.updateFirst(query, update, UserDO.class);
        }
    }

    @Override
    public void setLocation(String userId, String longitude, String latitude) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO != null) {
            Update update = new Update();
            update.set("latitude", latitude);
            update.set("longitude", longitude);
            mongoTemplate.updateFirst(query, update, UserDO.class);
        }
        return;
    }

    /**
     * 获取微信步数
     *
     * @param code
     * @param encryptedData
     * @param iv
     * @return
     */
    @Override
    public Map<String, Object> getWXStep(String code, String encryptedData, String iv) {
        Map<String, Object> map = new HashMap<String, Object>();

        //登录凭证不能为空
        if (code == null || code.length() == 0) {
            map.put("msg", "code 不能为空");
            return map;
        }
        //小程序唯一标识   (在微信小程序管理后台获取)
        String wxspAppid = UserConstantInterface.WX_LOGIN_APPID;
        //小程序的 app secret (在微信小程序管理后台获取)
        String wxspSecret = UserConstantInterface.WX_LOGIN_SECRET;
        //授权（必填）
        String grant_type = "authorization_code";
        //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid ////////////////
        //请求参数
        String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        //发送请求
        String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        //解析相应内容（转换成json对象）
        com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(sr);
        //获取会话密钥（session_key）
        String session_key = json.get("session_key").toString();
        //用户的唯一标识（openid）
        String openid = (String) json.get("openid");

        //////////////// 2、对encryptedData加密数据进行AES解密 ////////////////
        try {
            String result = AesUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
            if (null != result && result.length() > 0) {
                //System.out.println("result = " + result);
                map.put("msg", "解密成功");
                WXStepDO wxStepDO = JSON.parseObject(result, WXStepDO.class);
                if (wxStepDO != null) {
                    List<WXStepDO.StepInfoListBean> stepInfoList = wxStepDO.getStepInfoList();
                    WXStepDO.StepInfoListBean stepInfoListBean = stepInfoList.get(stepInfoList.size() - 1);
                    int step = stepInfoListBean.getStep();
                    userMissionManager.updateMission(openid, "step", step);
                }
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.put("msg", "解密失败");
        return map;
    }

    /**
     * 获取邀请二维码
     *
     * @param userId
     * @return
     */
    @Override
    public String getSharePoster(String userId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        if (!StringUtil.isEmpty(userDO.getSharePath())) {
            return userDO.getSharePath();
        }
        String poster = this.sharePoster(this.getQrcode(userId), userDO);
        Update update = new Update();
        update.set("share_path", poster);
        mongoTemplate.updateFirst(query, update, UserDO.class);
        return poster;
    }

    /**
     * 获取分享海报
     *
     * @param userId
     * @return
     */
    @Override
    public String getQrcode(String userId) {
        String requestUrl = UserConstantInterface.ACCESS_TOKEN_URL.replace("APPID", UserConstantInterface.WX_LOGIN_APPID).replace("APPSECRET", UserConstantInterface.WX_LOGIN_SECRET);
        String accessToken = this.getAccessToken(requestUrl);

        String ctxPath = UserConstantInterface.QR_CODE_UPLOAD_PATH;
        String fileName = RandomUtil.getRandomString(8) + ".png";
        String bizPath = "files";
        String nowDay = new SimpleDateFormat("yyyyMMdd").format(new Date());
        File file = new File(ctxPath + File.separator + bizPath + File.separator + nowDay);
        if (!file.exists()) {
            file.mkdirs();// 创建文件根目录
        }
        String savePath = file.getPath() + File.separator + fileName;
        String qrCode = bizPath + File.separator + nowDay + File.separator + fileName;
        if (qrCode.contains("\\")) {
            qrCode = qrCode.replace("\\", "/");
        }
        try {
            String wxCodeURL = UserConstantInterface.WX_CODE_URL.replace("ACCESS_TOKEN", accessToken);
            URL url = new URL(wxCodeURL);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            paramJson.put("scene", userId);

            paramJson.put("width", 430);
            paramJson.put("is_hyaline", true);
            paramJson.put("auto_color", true);

            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            //开始获取数据
            BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
            OutputStream os = new FileOutputStream(new File(savePath));
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1) {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return UserConstantInterface.IMG_PERFIX + qrCode;
    }

    /**
     * 获取微信请求使用的access_token 凭证
     *
     * @param requestUrl
     * @return
     * @throws Exception
     */
    private String getAccessToken(String requestUrl) {
        try {
            URL url = new URL(requestUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            // 设置通用的请求属性
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setUseCaches(false);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 得到请求的输出流对象
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.writeBytes("");
            out.flush();
            out.close();
            // 建立实际的连接
            connection.connect();
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = null;
            if (requestUrl.contains("nlp"))
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));
            else
                in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String result = "";
            String getLine;
            while ((getLine = in.readLine()) != null) {
                result += getLine;
            }
            in.close();
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            String accessToken = jsonObject.getString("access_token");
            return accessToken;
        } catch (Exception e) {
            logger.info("getAccessToken 异常:{}", e.getMessage());
        }
        return "";
    }

    /**
     * 生成海报
     *
     * @param qrcode
     * @param userDO
     * @return
     */
    private String sharePoster(String qrcode, UserDO userDO) {
        String nickName = StringUtil.isEmpty(userDO.getNickname()) ? "雷锋" : userDO.getNickname();
        String face = StringUtil.isEmpty(userDO.getFace()) ? "https://qiqiutree.leyougame.cc/timg.jpeg" : userDO.getFace();

        String poster = "https://qiqiutree.leyougame.cc/background.jpg?watermark/3/text/"
                + UrlSafeBase64.encodeToString(nickName) + "/font/5b6u6L2v6ZuF6buR/fill/"
                + UrlSafeBase64.encodeToString("#030303") + "/fontsize/500/dissolve/100/dx/138/dy/1230/gravity/NorthWest/image/"
                + UrlSafeBase64.encodeToString(face) + "/dissolve/100/dx/49/dy/1210/ws/0.11/gravity/NorthWest/image/"
                + UrlSafeBase64.encodeToString(qrcode) + "/dissolve/100/dx/32/dy/49/gravity/SouthEast/ws/0.23";
        return poster;
    }

    /**
     * 设置真实姓名
     *
     * @param userId
     * @param realname
     */
    @Override
    public void setRealname(String userId, String realname, String idCardNum, String phone) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        Update update = new Update();
        if (!TextUtils.isEmpty(realname)) {
            update.set("real_name", realname);
        }
        if (!TextUtils.isEmpty(idCardNum)) {
            update.set("id_card_num", idCardNum);
        }
        if (!TextUtils.isEmpty(phone)) {
            update.set("phone", phone);
        }
        update.set("gmt_modified", DateUtil.getDateline());
        mongoTemplate.updateFirst(query, update, UserDO.class);
        return;
    }

    /**
     * 获取志愿者证书
     *
     * @param userId
     * @return
     */
    @Override
    public String volunteerCert(String userId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        if (!StringUtil.isEmpty(userDO.getVolunteerCert())) {
            return userDO.getVolunteerCert();
        }
        String certNumber = RandomUtil.getRandomString(6);
        String realName = StringUtil.isEmpty(userDO.getRealName()) ? "雷锋" : userDO.getRealName();
        String qrCode = this.getQrcode(userId);

        String cert = "https://qiqiutree.leyougame.cc/WechatIMG6.jpg?watermark/3/text/"
                + UrlSafeBase64.encodeToString(realName) + "/font/5b6u6L2v6ZuF6buR/fill/"
                + UrlSafeBase64.encodeToString("#030303") + "/fontsize/800/dissolve/100/dx/580/dy/480/text/"
                + UrlSafeBase64.encodeToString("证书编号: " + certNumber) + "/font/5b6u6L2v6ZuF6buR/fill/"
                + UrlSafeBase64.encodeToString("#030303") + "/fontsize/420/dissolve/100/dx/520/dy/150/gravity/NorthWest/image/"
                + UrlSafeBase64.encodeToString(qrCode) + "/dissolve/100/dx/590/dy/110/gravity/SouthEast/ws/0.15";
        Update update = new Update();
        update.set("volunteer_cert", cert);
        mongoTemplate.updateFirst(query, update, UserDO.class);
        return cert;
    }

    /**
     * 获取日签图
     *
     * @param userId
     * @return
     */
    @Override
    public String getTodayLot(String userId) {
        Query queryUser = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(queryUser, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        String qrCode = this.getQrcode(userId);
        String dateFormat = DateUtil.toString(DateUtil.getDateline(), "yyyy-MM-dd");

        Query query = new Query(Criteria.where("date").is(dateFormat));
        DailyLotDO lotDO = mongoTemplate.findOne(query, DailyLotDO.class);
        //没有背景图
        if (lotDO == null) {
            return "";
        }
        Integer duration = userDO.getDuration() == null ? 0 : userDO.getDuration();
        String background = lotDO.getBackground();
        String cert = background + "?watermark/3/text/"
                + UrlSafeBase64.encodeToString(duration.toString()) + "/font/5b6u6L2v6ZuF6buR/fill/"
                + UrlSafeBase64.encodeToString("#ffffff") + "/fontsize/2500/dissolve/100/dx/202/dy/1050/text/"
                + UrlSafeBase64.encodeToString(DateUtil.toString(DateUtil.getDateline(), "yyyy年MM月dd日 ") + DateUtil.weekDays()) + "/font/5b6u6L2v6ZuF6buR/fill/"
                + UrlSafeBase64.encodeToString("#48bfb5") + "/fontsize/600/dissolve/100/dx/130/dy/230/image/"
                + UrlSafeBase64.encodeToString(qrCode) + "/dissolve/100/dx/495/dy/85/gravity/SouthEast/ws/0.25";
        //更新任务状态
        userMissionManager.updateMission(userId, "signature", null);
        return cert;
    }

    /**
     * 增加累计成长值
     */
    @Override
    public void addTotalGrow(String userId, Integer num) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), "用户不存在");
        }
        Integer totalGrow = userDO.getTotalGrow();
        if(totalGrow!=null) {
            Update update = new Update();
            update.set("total_grow", totalGrow + num);//总能量增加
            update.set("gmt_modified", DateUtil.getDateline() + "");
            mongoTemplate.updateFirst(query, update, UserDO.class);
        }
    }

    @Override
    public void updateUserGrowValue() {
        Query query = new Query(Criteria.where("user_id").ne(""));
        List<UserDO> userDOS = mongoTemplate.find(query, UserDO.class);
        for (int i = 0; i < userDOS.size(); i++) {
            int growValue = 0;
            //用户的树木
            Query queryTree = new Query(Criteria.where("user_id").is(userDOS.get(i).getUserId()));
            List<UserTreeDO> userTreeDOS = mongoTemplate.find(queryTree, UserTreeDO.class);
            if (userTreeDOS.size() > 0) {
                for (int j = 0; j < userTreeDOS.size(); j++) {
                    growValue += userTreeDOS.get(j).getCurrentValue();
                }
                Query queryUser = new Query(Criteria.where("user_id").is(userDOS.get(i).getUserId()));
                Update update = new Update();
                update.set("total_grow", growValue);
                mongoTemplate.updateFirst(queryUser, update, UserDO.class);
            }
        }
        return;
    }

    /**
     * 自动生成水滴
     */
    @Override
    public void updateWater() {
        List<UserDO> allUsers = mongoTemplate.findAll(UserDO.class);
        for (UserDO userDO : allUsers) {
            if (userDO!=null){
                if (userDO.getWater() != null && userDO.getWater() == 10) {
                    continue;
                }
                Long lastWaterTime = userDO.getLastWaterTime();
                if (lastWaterTime == null) {
                    continue;
                }
                long hourTime = DateUtil.getHourTime(lastWaterTime);
                if(hourTime>=3){
                    addWater(userDO.getUserId(), userDO.getWater());
                }
            }
        }
    }

    /**
     * 偷水或领取水滴
     * @param userId
     * @param friend_id
     * @return
     */
    @Override
    public Map<String, String> receiveWater(String userId, String friend_id) {
        subWater(userId, friend_id);
        return null;
    }

    /**
     * 增加水滴
     */
    private void addWater(String userId, Integer currentWater) {
        if (currentWater == null) {
            currentWater = 0;
        }
        int water = currentWater + 6;
        if(water>=10){
            water = 10;
        }
        Update update = new Update();
        update.set("water", water);//总能量增加
        update.set("last_water_time", DateUtil.getDateline());//设置时间
        Query query = new Query(Criteria.where("user_id").is(userId));
        mongoTemplate.updateFirst(query, update, UserDO.class);
    }

    /**
     * 减少水滴
     */
    private void subWater(String userId, String friendId) {
        Query query;
        if(friendId==null){
            query = new Query(Criteria.where("user_id").is(userId));
        }else {
            query = new Query(Criteria.where("user_id").is(friendId));
        }
        UserDO userDO = mongoTemplate.findOne(query, UserDO.class);
        if(userDO!=null){
            Integer w = userDO.getWater();
            Integer water = userDO.getWater();
            if(friendId == null){
                //领取自己的，直接清空
                water = 0;
            }else {
                //偷取别人的
                Query queryReceive = new Query(Criteria.where("receive_id").is(friendId).and("date").is(DateUtil.startOfTodDay()).and("user_id").is(userId));
                ReceiveWaterDO one = mongoTemplate.findOne(queryReceive, ReceiveWaterDO.class);
                if (one != null) {
                    throw new ServiceException(ErrorCodeEnum.E305.code(), "今日已领取过");
                }
                Query queryNum = new Query(Criteria.where("user_id").is(userId).and("date").is(DateUtil.startOfTodDay()));
                long count = mongoTemplate.count(queryNum, ReceiveWaterDO.class);
                if (count >= 20) {
                    throw new ServiceException(ErrorCodeEnum.E306.code(), "邻居家的水借的太多了，明天再来吧");
                }
                if (water <= 4) {
                    throw new ServiceException(ErrorCodeEnum.E304.code(), "数量太少，无法偷取");
                }
                water = Math.max(water - 1, 0);
            }
            Update update = new Update();
            update.set("water", water);//设置水滴
            mongoTemplate.updateFirst(query, update, UserDO.class);

            if (friendId == null) {
                //增加真实水滴道具
                if (w != null) {
                    userPropManager.addProp(userId, "WATER", w);
                }
            } else {
                //偷取别人的
                userPropManager.addProp(userId, "WATER", 1);

                //设置偷取时间与偷取的信息
                ReceiveWaterDO receiveWaterDO = new ReceiveWaterDO();
                receiveWaterDO.setUserId(userId);
                receiveWaterDO.setReceiveId(friendId);
                receiveWaterDO.setDate(DateUtil.startOfTodDay());
                mongoTemplate.insert(receiveWaterDO);
            }
        }
    }

    /**
     * 设置上次生成水时间
     */
    private void addWaterTime(String userId){
        Query query = new Query(Criteria.where("user_id").is(userId));
        Update update = new Update();
        update.set("last_water_time", DateUtil.getDateline());//设置时间
        mongoTemplate.updateFirst(query, update, UserDO.class);
    }
}
